/** * Copyright 2010 CosmoCode GmbH * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package de.cosmocode.palava.servlet.jetty; import java.net.URL; import java.util.List; import java.util.Set; import org.eclipse.jetty.server.Handler; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.server.handler.ContextHandlerCollection; import org.eclipse.jetty.servlet.DefaultServlet; import org.eclipse.jetty.servlet.ServletContextHandler; import org.eclipse.jetty.xml.XmlConfiguration; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.google.common.base.Preconditions; import com.google.common.collect.Lists; import com.google.inject.Inject; import com.google.inject.Provider; import com.google.inject.internal.Sets; import com.google.inject.name.Named; import com.google.inject.servlet.GuiceFilter; import de.cosmocode.palava.core.lifecycle.Disposable; import de.cosmocode.palava.core.lifecycle.Initializable; import de.cosmocode.palava.core.lifecycle.LifecycleException; import de.cosmocode.palava.servlet.Webapp; /** * A service which configured and manages an embedded jetty server. * * @author Tobias Sarnowski * @author Willi Schoenborn */ final class Jetty implements Initializable, Disposable, Provider<Server> { private static final Logger LOG = LoggerFactory.getLogger(Jetty.class); private URL config; private Set<Webapp> webapps = Sets.newLinkedHashSet(); private int port; private Server jetty; @Inject(optional = true) void setWebapps(Set<Webapp> webapps) { this.webapps = Preconditions.checkNotNull(webapps, "Webapps"); } @Inject(optional = true) void setConfig(@Named(JettyConfig.CONFIG) URL config) { this.config = config; } @Inject(optional = true) void setPort(@Named(JettyConfig.PORT) int port) { this.port = port; } @Override public void initialize() throws LifecycleException { if (port < 0) { jetty = new Server(); } else { jetty = new Server(port); } final ContextHandlerCollection contexts = new ContextHandlerCollection(); jetty.setHandler(contexts); new ServletContextHandler(contexts, "/", ServletContextHandler.SESSIONS); final List<Handler> handlers = Lists.newArrayList(); if (webapps.isEmpty()) { LOG.info("No programmatically added webapp to configure."); } else { for (Webapp webapp : webapps) { LOG.info("Adding webapp {}", webapp); final ServletContextHandler handler = new ServletContextHandler( contexts, webapp.getContext(), ServletContextHandler.SESSIONS); // add guice servlet filter // http://code.google.com/p/google-guice/wiki/ServletModule handler.addFilter(GuiceFilter.class, "/*", 0); handler.setResourceBase(webapp.getLocation()); handler.addServlet(DefaultServlet.class, "/"); handlers.add(handler); } } contexts.setHandlers(handlers.toArray(new Handler[handlers.size()])); // configure with jetty.xml if (config == null) { LOG.info("No configuration file given to load."); } else { try { LOG.info("Loading configuration {}", config); new XmlConfiguration(config).configure(jetty); /* CHECKSTYLE:OFF */ } catch (Exception e) { /* CHECKSTYLE:ON */ throw new LifecycleException(e); } } try { jetty.start(); /* CHECKSTYLE:OFF */ } catch (Exception e) { /* CHECKSTYLE:ON */ throw new LifecycleException(e); } } @Override public void dispose() throws LifecycleException { try { jetty.stop(); /* CHECKSTYLE:OFF */ } catch (Exception e) { /* CHECKSTYLE:ON */ throw new LifecycleException(e); } } @Override public Server get() { return jetty; } }